(function ( exports ) {
    //region W3Org2011XmlSchemaValue

    function W3Org2011XmlSchemaValue ( value ) {
        COSA.XrmValue.call(this, value);
    }

    COSA.Util.deriveOverride(COSA.XrmValue, W3Org2011XmlSchemaValue, {
        type: '',
        namespace: 'http://www.w3.org/2001/XMLSchema',
        requireTypeDef: true,
        getTemplate: function () {
            return this.value.toString();
        }
    });

    //endregion W3Org2011XmlSchemaValue

    //region XrmString

    /**
     * Contains data that is needed for 'string' type representation in CRM OrganizationRequest
     * @param {string} value String value
     * @prop {string} value String value
     * @memberOf COSA
     * @constructor XrmString
     */
    function XrmString ( value ) {
        W3Org2011XmlSchemaValue.call(this, value);
    }

    COSA.Util.deriveOverride(W3Org2011XmlSchemaValue, XrmString, {
        type: 'string',
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .typeOf('string');
        }
    });

    //endregion XrmString

    //region XrmDateTime

    /**
     * Contains data that is needed for 'DateTime' type representation in CRM OrganizationRequest
     * @param {Date} value Date value
     * @param {string} formattedValue Formatted values
     * @memberOf COSA
     * @constructor XrmDateTime
     */
    function XrmDateTime ( value, formattedValue ) {
        W3Org2011XmlSchemaValue.call(this, value);
        this.formattedValue = formattedValue;
    }

    COSA.Util.deriveOverride(W3Org2011XmlSchemaValue, XrmDateTime, {
        type: 'dateTime',
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .instanceOf(Date);
        },
        getTemplate: function () {
            return (new COSA.XrmEncoder()).encodeDate(this.value);
        }
    });

    //endregion XrmDateTime

    //region XrmWholeNumber

    /**
     * Contains data that is needed for 'WholeNumber' type representation in CRM OrganizationRequest
     * @param {number} value Whole number value
     * @prop {number} value Whole number value
     * @memberOf COSA
     * @constructor XrmWholeNumber
     */
    function XrmWholeNumber ( value ) {
        W3Org2011XmlSchemaValue.call(this, value);
    }

    COSA.Util.deriveOverride(W3Org2011XmlSchemaValue, XrmWholeNumber, {
        type: 'int',
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .int();
        }
    });

    //endregion XrmWholeNumber

    //region XrmBoolean

    /**
     * Contains data that is needed for 'WholeNumber' type representation in CRM OrganizationRequest
     * @param {boolean} value Boolean value
     * @prop {boolean} value Boolean value
     * @memberOf COSA
     * @constructor XrmBoolean
     */
    function XrmBoolean ( value ) {
        W3Org2011XmlSchemaValue.call(this, value);
        this.formattedValue = '';
    }

    COSA.Util.deriveOverride(W3Org2011XmlSchemaValue, XrmBoolean, {
        type: 'boolean',
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .typeOf('boolean');
        }
    });

    //endregion XrmBoolean

    //region XrmDouble

    /**
     * Contains data that is needed for 'XrmDouble' type representation in CRM OrganizationRequest
     * @param {number} value
     * @prop {number} value
     * @memberOf COSA
     * @constructor XrmDouble
     */
    function XrmDouble ( value ) {
        W3Org2011XmlSchemaValue.call(this, value);
    }

    COSA.Util.deriveOverride(W3Org2011XmlSchemaValue, XrmDouble, {
        type: 'double',
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .typeOf('number');
        }
    });

    //endregion XrmDouble

    //region XrmGuid

    /**
     * Contains data that is needed for 'GUID' type representation in CRM OrganizationRequest
     * @param {string} guidStr GUID string
     * @prop {string} value GUID string
     * @memberOf COSA
     * @constructor XrmGuid
     */
    function XrmGuid ( guidStr ) {
        COSA.XrmValue.call(this, guidStr);
    }

    COSA.Util.deriveOverride(COSA.XrmValue, XrmGuid, {
        namespace: 'http://schemas.microsoft.com/2003/10/Serialization/',
        type: 'guid',
        requireTypeDef: true,
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .typeOf('string')
                .guid();
        }
    });

    //endregion XrmGuid

    //region XrmDecimal

    /**
     * Contains data that is needed for 'Decimal' type representation in CRM OrganizationRequest
     * @param {number} value Decimal value
     * @prop {number} value Decimal value
     * @memberOf COSA
     * @constructor XrmDecimal
     */
    function XrmDecimal ( value ) {
        W3Org2011XmlSchemaValue.call(this, value);
    }

    COSA.Util.deriveOverride(W3Org2011XmlSchemaValue, XrmDecimal, {
        type: 'decimal'
    });

    //endregion XrmDecimal

    //region EntityFilters

    /**
     * Entity filters
     * @param {string} filtersString Filters value
     * @prop {string} value Filters value
     * @memberOf COSA
     * @constructor EntityFilters
     */
    function EntityFilters ( filtersString ) {
        COSA.XrmValue.call(this, filtersString);
    }

    COSA.Util.deriveOverride(COSA.XrmValue, EntityFilters, {
        type: 'EntityFilters',
        requireTypeDef: true,
        namespace: 'http://schemas.microsoft.com/xrm/2011/Metadata',
        validate: function () {
            (new COSA.ValueChecker(this.value))
                .defined()
                .typeOf('string');
        }
    });

    //endregion EntityFilters

    exports.XrmString = XrmString;
    exports.XrmDateTime = XrmDateTime;
    exports.XrmWholeNumber = XrmWholeNumber;
    exports.XrmBoolean = XrmBoolean;
    exports.XrmDouble = XrmDouble;
    exports.XrmGuid = XrmGuid;
    exports.XrmDecimal = XrmDecimal;
    exports.EntityFilters = EntityFilters;

})(COSA);
